package com.anlogic.sdk.templates.core.processes;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.cdt.core.templateengine.TemplateCore;
import org.eclipse.cdt.core.templateengine.TemplateEngineHelper;
import org.eclipse.cdt.core.templateengine.process.ProcessArgument;
import org.eclipse.cdt.core.templateengine.process.ProcessFailureException;
import org.eclipse.cdt.core.templateengine.process.ProcessHelper;
import org.eclipse.cdt.core.templateengine.process.ProcessRunner;
import org.eclipse.cdt.core.templateengine.process.processes.Messages;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;

import com.anlogic.sdk.templates.core.Activator;
import com.anlogic.sdk.templates.core.Utils;


/**
 * Adds Files to the Project
 */
public class ConditionalDeepCopyFolders extends ProcessRunner {

	/**
	 * This method Adds the list of Files to the corresponding Project.
	 */
	@Override
	public void process(TemplateCore template, ProcessArgument[] args, String processId, IProgressMonitor monitor)
			throws ProcessFailureException {
		IProject projectHandle = null;
		ProcessArgument[][] folders = null;
		String startPattern = null;
		String endPattern = null;
		String condition = null;

		for (ProcessArgument arg : args) {
			String argName = arg.getName();
			if (argName.equals("projectName")) { //$NON-NLS-1$
				projectHandle = ResourcesPlugin.getWorkspace().getRoot().getProject(arg.getSimpleValue());
			} else if (argName.equals("folders")) { //$NON-NLS-1$
				folders = arg.getComplexArrayValue();
			} else if (argName.equals("condition")) { //$NON-NLS-1$
				condition = arg.getSimpleValue();
			}
		}

		if (projectHandle == null)
			throw new ProcessFailureException(getProcessMessage(processId, IStatus.ERROR, "projectName not specified")); //$NON-NLS-1$

		if (folders == null)
			throw new ProcessFailureException(getProcessMessage(processId, IStatus.ERROR, "No folders")); //$NON-NLS-1$

		if (!Utils.isConditionSatisfied(condition))
			return;

		for (int i = 0; i < folders.length; i++) {
			ProcessArgument[] folder = folders[i];
			String folderSourcePath = folder[0].getSimpleValue();
			String folderTargetPath = folder[1].getSimpleValue();
			String pattern = folder[2].getSimpleValue().trim();
			boolean replaceable = folder[3].getSimpleValue().equals("true"); //$NON-NLS-1$
			
			// System.out.println(folderSourcePath);
			// System.out.println(folderTargetPath);
			// System.out.println(pattern);
			File dir = new File(folderSourcePath);
			try {
				if (!dir.isAbsolute()) {
					URL folderURL;
					folderURL = TemplateEngineHelper.getTemplateResourceURLRelativeToTemplate(template,
							folderSourcePath);
					if (folderURL == null) {
						throw new ProcessFailureException(getProcessMessage(processId, IStatus.ERROR,
								Messages.getString("AddFiles.1") + folderSourcePath)); //$NON-NLS-1$
					}

					// System.out.println(folderURL.getFile());
					dir = new File(folderURL.getFile());
				}
			} catch (IOException e) {
				Activator.log(e);
			}
			deepCopyFolder(template, processId, projectHandle, dir, folderSourcePath, folderTargetPath, pattern, startPattern, endPattern, replaceable);
		}
		try {
			projectHandle.refreshLocal(IResource.DEPTH_INFINITE, null);
		} catch (CoreException e) {
			throw new ProcessFailureException(Messages.getString("AddFiles.7") + e.getMessage(), e); //$NON-NLS-1$
		}
	}
	
	public void deepCopyFolder(TemplateCore template, String processId, IProject projectHandle, File dir, String folderSourcePath, String folderTargetPath, String pattern, String startPattern, String endPattern, boolean replaceable) throws ProcessFailureException {
		if (dir.isDirectory()) {
			for (File child : dir.listFiles()) {
				// System.out.println(child);
				// System.out.println(child.getName());

				String fileName = child.getName();
				if (pattern.length() > 0) {
					if (!fileName.matches(pattern)) {
						if (Activator.getInstance().isDebugging()) {
							System.out.println(fileName + " skipped");
						}
						continue;
					}
				}

				String newFolderSourcePath = (new File(folderSourcePath, fileName)).getPath();
				String newFolderTargetPath = (new File(folderTargetPath, fileName)).getPath();
				deepCopyFolder(template, processId, projectHandle, child, newFolderSourcePath, newFolderTargetPath, pattern, startPattern, endPattern, replaceable);
			}
		} else {
			URL sourceURL;
			try {
				sourceURL = dir.toURL(); // using .toURI().toURL()
											// fails,
											// due to
											// spaces substitution

			} catch (MalformedURLException e2) {
				throw new ProcessFailureException(Messages.getString("AddFiles.2") + folderSourcePath); //$NON-NLS-1$
			}

			InputStream contents = null;
			if (replaceable) {
				String fileContents;
				try {
					fileContents = ProcessHelper.readFromFile(sourceURL);
				} catch (IOException e) {
					throw new ProcessFailureException(Messages.getString("AddFiles.3") + folderSourcePath); //$NON-NLS-1$
				}
				if (startPattern != null && endPattern != null)
					fileContents = ProcessHelper.getValueAfterExpandingMacros(fileContents,
							ProcessHelper.getReplaceKeys(fileContents, startPattern, endPattern),
							template.getValueStore(), startPattern, endPattern);
				else
					fileContents = ProcessHelper.getValueAfterExpandingMacros(fileContents,
							ProcessHelper.getReplaceKeys(fileContents), template.getValueStore());

				contents = new ByteArrayInputStream(fileContents.getBytes());
			} else {
				try {
					contents = sourceURL.openStream();
				} catch (IOException e) {
					throw new ProcessFailureException(getProcessMessage(processId, IStatus.ERROR,
							Messages.getString("AddFiles.4") + folderSourcePath)); //$NON-NLS-1$
				} finally {
					if (contents != null)
						try {
							contents.close();
						} catch (IOException e) {
							throw new ProcessFailureException(getProcessMessage(processId, IStatus.ERROR,
									Messages.getString("AddFiles.4") + folderSourcePath)); //$NON-NLS-1$
						}
				}
			}

			try {
				IFile iFile = projectHandle.getFile(folderTargetPath);
				
				if (iFile.isHidden() || Utils.isHidden(folderTargetPath)) {
					return ;
				}
				
				if (!iFile.getParent().exists()) {
					ProcessHelper.mkdirs(projectHandle,
							projectHandle.getFolder(iFile.getParent().getProjectRelativePath()));
				}
				
				if (iFile.exists()) {
					// honor the replaceable flag and replace the
					// file
					// contents
					// if the file already exists.
					if (replaceable) {
						iFile.setContents(contents, true, true, null);
					} else {
						throw new ProcessFailureException(Messages.getString("AddFiles.5")); //$NON-NLS-1$
					}

				} else {
					iFile.create(contents, true, null);
					iFile.refreshLocal(IResource.DEPTH_ONE, null);
				}
			} catch (CoreException e) {
				throw new ProcessFailureException(Messages.getString("AddFiles.6") + e.getMessage(), e); //$NON-NLS-1$
			}
		}
	}
}

